package bibbletex.models;

import java.util.UUID;
import java.sql.ResultSet;
import java.sql.SQLException;
import bibbletex.helpers.SQLHelper;

/**
 * Model for a reference
 * 
 * TODO: create subclasses for the different types instead of having
 * ReferenceType?
 * 
 * @author Diego Barrios Romero
 * 
 */
public class Reference {

	/**
	 * Type of reference
	 * 
	 * @author Diego Barrios Romero
	 * 
	 */
	public enum ReferenceType {
		ARTICLE, BOOK;
	};

	/**
	 * Unique identifier. This will also work as the primary key in the
	 * database.
	 */
	UUID id;
	String title, authors;

	ReferenceType type;

	/**
	 * Constructor with ID, to be used only by load
	 * 
	 * @param id
	 *            UUID loaded
	 */
	public Reference(UUID id) {
		this.id = id;
	}

	/**
	 * Copy constructor
	 * 
	 * @param r
	 *            Reference
	 */
	public Reference(Reference r) {
		id = r.getId();
		setTitle(r.getTitle());
		setType(r.getType());
		setAuthors(r.getAuthors());
	}

	/**
	 * Constructor to be used with form data
	 * 
	 * @param rr
	 *            request data
	 */
	public Reference(RequestReference rr) {
		id = UUID.randomUUID();
		setTitle(rr.getTitle());
		setType(rr.getType());
		setAuthors(rr.getAuthors());
	}

	public UUID getId() {
		return id;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title_) {
		title = new String(title_);
	}

	public String getAuthors() {
		return authors;
	}

	public void setAuthors(String authors_) {
		authors = new String(authors_);
	}

	public ReferenceType getType() {
		return type;
	}

	public void setType(ReferenceType type_) {
		// WARNING: Reference!
		type = type_;
	}

	public void setType(String type_) {
		if (type_.toUpperCase().equals("ARTICLE"))
			type = ReferenceType.ARTICLE;
		else if (type_.toUpperCase().equals("BOOK"))
			type = ReferenceType.BOOK;
		else
			System.err.println("Reference: Unknown type: " + type_);
	}

	/* HELPER METHODS */
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj instanceof Reference) {
			Reference other = (Reference) obj;
			// By definition, the UUID are uniques so we only need to
			// compare the ID
			return (id.equals(other.id));
		} else {
			return false;
		}
	}

	/* CLASS METHODS */
	/**
	 * This method saves a given reference in the database
	 * @param r Reference to save
	 * @return Whether the operation was successful
	 */
	public static boolean save(Reference r) {
		ResultSet rs = null;
		boolean success = false;

		// if exists, update, if not, insert
		rs = SQLHelper.execQuerySQL("select * from reference where id = '"
				+ r.getId() + "'");

		try {
			if (rs.next()) {
				// Update
				success = SQLHelper.execSQL("update reference set id = '"
						+ r.getId() + "', type = '" + r.getType()
						+ "', title = '" + r.getTitle() + "', authors = '"
						+ r.getAuthors() + "' where id = '" + r.getId() + "'");
			} else {
				// Insert
				success = SQLHelper.execSQL("insert into reference values('"
						+ r.getId() + "', '" + r.getType() + "', '"
						+ r.getTitle() + "', '" + r.getAuthors() + "')");
			}
		} catch (SQLException e) {
			System.err.println("Reference.save: " + e);
		}

		return success;
	}

	/**
	 * Delete a reference from the database
	 * @param r Reference to delete
	 * @return Whether the operation was successful
	 */
	public static boolean delete(Reference r) {
		return SQLHelper.execSQL("delete from reference where id='" + r.getId()
				+ "'");
	}

	/**
	 * This method loads the reference with the given ID from the database
	 * @param id UUID of the reference to load
	 * @return Loaded Reference
	 */
	public static Reference load(String id) {
		Reference r = null;
		ResultSet rs = null;

		try {
			rs = SQLHelper.execQuerySQL("select * from reference where id='"
					+ id + "'");

			if (rs.next()) {
				r = new Reference(UUID.fromString(rs.getString("id")));
				r.setType(rs.getString("type"));
				r.setTitle(rs.getString("title"));
				r.setAuthors(rs.getString("authors"));
			}

		} catch (SQLException e) {
			System.err.println("Reference.load: " + e);
		}

		return r;
	}
}
